package se.webbzon.boltzmann.game.object.pickup;

import javax.vecmath.Vector3d;

import se.webbzon.boltzmann.sound.SoundUtils;
import se.webbzon.oschi01.collision3d.CollisionCube3D;
import se.webbzon.oschi01.utilities.ArrayUtils;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldMovableObject;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XYPlaneAppearance3D;

public class Loot extends WorldMovableObject {
	
	// The y-velocity of the loot 
	private static final double minSpeed = 4, maxSpeed = 6;
	
	// The actual loot of this loot instance
	private final WorldStaticObject loot;
	
	// The shadow of this loot
	private final LootShadow shadow;
	
	// Whatever this instance is solidified
	private boolean solidified;
	
	/*============================================================
	Constructors
	============================================================*/

	public Loot(WorldStaticObject loot) {
		super(WorldObject.onCreate + WorldObject.onStep + WorldObject.onDestroy, 
				new XYPlaneAppearance3D());
		this.loot = loot;
		setMask(new CollisionCube3D());
		shadow = new LootShadow(this);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public void onCreate(WorldArea world) {
		mimic(loot);
		setAcceleration(0, -0.5, 0);
		setVelocity(getXVelocity(), minSpeed + (maxSpeed - minSpeed) * Math.random(), getZVelocity());
		shadow.launch(world);
		solidified = false;
	}

	@Override public void onStep(WorldArea world) {
		setSolid(true);
		Vector3d pos = getTranslation();
		if (solidified) {
			if (getYVelocity() < 0) {
				pos.set(pos.getX(), pos.getY() + getYVelocity(), pos.getZ());
				if (!world.placeFree(this, pos, null, null)) {
					SoundUtils.playSound(ArrayUtils.random("bounce_01","bounce_02","bounce_03"));
					if (getYVelocity() > -2) {
						world.moveContact(this, getVelocity(), 2);
						setVelocity(0,0,0);
						world.destroyInstance(this);
					} else {
						double vx = 0.8 * getXVelocity();
						double vy = -0.5 * getYVelocity();
						double vz = 0.8 * getZVelocity();
						setVelocity(vx,vy,vz);
					}
				}
				getTranslation(pos);	
			} 
			if (getXVelocity() != 0 || getZVelocity() != 0) {
				pos.set(pos.getX() + getXVelocity(), pos.getY(), pos.getZ() + getZVelocity());
				if (!world.placeFree(this, pos, null, null)) {
					setVelocity(0,getYVelocity(),0);
				}
			}
		} else {
			solidified = world.placeFree(this, null, null, null);
		}
		setSolid(false);
	}

	@Override public void onDestroy(WorldArea world) {
		reflect(loot);
		world.createInstance(loot);
		shadow.terminate(world);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Forces the loot instance to mimic the provided instance in appearance. **/
	private final void mimic(WorldStaticObject instance) {
		Appearance3D lootApp = instance.getAppearance();
		if (lootApp instanceof SimpleAppearance3D) {
			SimpleAppearance3D lootSimpApp = (SimpleAppearance3D) lootApp;
			SimpleAppearance3D simpApp = (SimpleAppearance3D) getAppearance();
			simpApp.setTextureSet(lootSimpApp.getTextureSet());
			simpApp.setTextureIndex(lootSimpApp.getTextureIndex());
			simpApp.setTextureSpeed(lootSimpApp.getTextureSpeed());
		}
		setSize(instance.getWidth(),instance.getHeight(),instance.getDepth());
		setRotation(instance.getEX(),instance.getEY(), instance.getEZ(), instance.getAngle());
		setPosition(instance.getX(), instance.getY(), instance.getZ());
	}
	
	/** Reflects the appearance of this loot instance onto the provided instance. **/
	private final void reflect(WorldStaticObject instance) {
		Appearance3D lootApp = instance.getAppearance();
		if (lootApp instanceof SimpleAppearance3D) {
			SimpleAppearance3D lootSimpApp = (SimpleAppearance3D) lootApp;
			SimpleAppearance3D simpApp = (SimpleAppearance3D) getAppearance();
			lootSimpApp.setTextureSet(simpApp.getTextureSet());
			lootSimpApp.setTextureIndex(simpApp.getTextureIndex());
			lootSimpApp.setTextureSpeed(simpApp.getTextureSpeed());
		}
		instance.setSize(getWidth(), getHeight(),getDepth());
		instance.setRotation(getEX(), getEY(), getEZ(), getAngle());
		instance.setPosition(getX(), getY(), getZ());
	}

}
